<script setup lang="ts">
import { computed, ref, useTemplateRef } from 'vue';
import {
  useColHeight,
  useColWidth,
  useImageHeight,
  useImageLocation
} from './composables';

const props = withDefaults(
  defineProps<{
    data: Record<string, any>[] | null;
    nodeKey: string;
    columns: number;
    columnGap: number;
    rowGap: number;
    picturePreReading: boolean;
  }>(),
  {
    data: null,
    nodeKey: 'index',
    columns: 2,
    columnGap: 20,
    rowGap: 20,
    picturePreReading: true
  }
);

const computedData = computed(() => props.data);
const computedColumns = computed(() => props.columns);

// 瀑布流组件容器
const containerRef = useTemplateRef<HTMLDivElement>('containerRef');

// 每列宽度
const { colWidth, containerLeft } = useColWidth(containerRef, props);
const computedColWidth = computed(() => colWidth.value);
const widthCls = computed(() => `w-[${colWidth.value}px]`);

const itemHeights = ref<number[]>([]);
const {
  getItemRef,
  getItemHeightsAsync,
  getItemHeightsSync,
  updateItemHeightsSync,
  updateItemHeightAsync
} = useImageHeight();

// 瀑布流容器高度(最高的列的高度)
const containerHeight = ref<number>(0);
// 初始化每列高度
const { colHeight } = useColHeight({
  columns: computedColumns,
  data: computedData
});
const computedColHeight = computed(() => colHeight.value);

useImageLocation({
  data: computedData,
  columns: computedColumns,
  containerLeft,
  picturePreReading: props.picturePreReading,
  colGap: props.columnGap,
  rowGap: props.rowGap,
  containerHeight,
  itemHeights,
  getItemHeightsAsync,
  getItemHeightsSync,
  updateItemHeightsSync,
  updateItemHeightAsync,
  colHeight: computedColHeight,
  colWidth: computedColWidth
});

defineOptions({ name: 'MWaterfall' });
</script>

<template>
  <div
    class="relative"
    ref="containerRef"
    :style="{ height: `${containerHeight}px` }"
  >
    <template v-if="colWidth && props.data?.length">
      <div
        v-for="(item, index) in props.data"
        :key="item[props.nodeKey] || index"
        :ref="el => getItemRef(el as HTMLDivElement)"
        class="absolute duration-300"
        :class="widthCls"
        :style="{
          width: `${colWidth}px`,
          transform: `translate(${item._style?.left - 10}px, ${item._style?.top}px)`,
          transition: 'transform .7s'
        }"
      >
        <slot :item="item" :width="colWidth" :index="index" />
      </div>
    </template>
    <div v-else>加载中...</div>
  </div>
</template>
